﻿// DPRegShiftRegOperand2.cs
// Contains a class for a register shifted register oprerand 2 for a data processing instruction

using System;


namespace armsim
{

    /// <summary>
    /// Class for a Register shifted by register Operand2 of a Data Processing Instruction
    /// </summary>
    public class DPRegShiftRegOperand2 : DPOperand2
    {

        /// <summary>
        /// The register whose value is to be used to shift
        /// </summary>
        public uint Rs { get; protected set; }

        /// <summary>
        /// The kind of shift to be shifted by
        /// </summary>
        public uint Sh { get; protected set; }

        /// <summary>
        /// The register whose value is to be shifted
        /// </summary>
        public uint Rm { get; protected set; }


        /// <summary>
        /// Initializes a new DPRegShiftRegOperand2 with the Rs, Sh, and Rm values set
        /// </summary>
        /// <param name="instruction">32 bit arm instruction to decode from</param>
        public DPRegShiftRegOperand2(uint instruction) : base(instruction)
        {
            this.Rs = VirtualMemory.ExtractBits(instruction, 8, 11);
            this.Sh = VirtualMemory.ExtractBits(instruction, 5, 6);
            this.Rm = VirtualMemory.ExtractBits(instruction, 0, 3);
        }

        /// <summary>
        /// Returns the computed value of this operand
        /// </summary>
        /// <param name="cpu">Virtual cpu to get information from</param>
        /// <returns>value to be used in an instruction</returns>
        public override uint ComputeValue(VirtualCPU cpu)
        {
            return BarrelShifter.Shift(this.Sh, cpu.Registers.ReadRegistersDuringExecute(VirtualMemory.MapRegNoToRegMem(this.Rm)),
                                       cpu.Registers.ReadRegistersDuringExecute(VirtualMemory.MapRegNoToRegMem(this.Rs)));
        }

        /// <summary>
        /// Converts the Operand into assembly language
        /// </summary>
        /// <param name="cpu">the VirtualCPU to retrieve values from</param>
        /// <returns>a string with the number in assembly language style. base 10.</returns>
        public override string ToAssembly(VirtualCPU cpu)
        {
            return String.Format("{0}, {1} {2}", VirtualMemory.RegToAssembly(Rm), BarrelShifter.ToAssembly(Sh), VirtualMemory.RegToAssembly(Rs));
        }
    }
}
